#include <iostream>
#include <string>
//#include <C:\Program Files\Microsoft Platform SDK\Include\windows.h>
//#include "C:\Program Files\Microsoft Platform SDK\Include\Winsvc.h"

using namespace std;
#ifndef __aop_h
#define __aop_h



#ifndef __mysocket_h_
//#include "MySocket.h"
#endif


extern struct MethodInfo * MethodMOP;



static char buf[12];


#define WEAVE 8
#define UNWEAVE 9

enum  NetworkType  { BROADCAST,SUBNET,MULTICAST,HGROUPJP,HOST,LOCAL};
enum  JPType  { ALL,GROUPJP,NAMEMATCH};
enum  WeaveTarget {Method_W,Variable_W,Application_W};
enum  WeaveType   {Before_T,After_T,Around_T,Start_T,Finish_T};
enum  RoleType    {Client_R,Server_R, Local_R,CL_R,CS_R};

extern string AOPApplication,AOPApplication_mang;
extern RoleType HostRole;

//pthread_mutex_t request_mutex = PTHREAD_MUTEX_INITIALIZER;

extern HANDLE request_mutex; 


//pthread_mutex_t sharedMD_mutex = PTHREAD_MUTEX_INITIALIZER;

extern string WeavingRequestsQueue[50];  // FIFO queue
extern int    WeavingRequestsQueueSize; // WRQS



extern bool RequestPending;


void check_for_requests();
void startup();

 UINT aopengine_thread( LPVOID pParam );
//pthread_t aopengine_thread;


char* dac_itoa(int i);
/////////////////////////////////////////////////
class  ApplicationPC {
public: 


    ApplicationPC() ;
   ApplicationPC( JPType thetype, string thevalue) ;
void   printinfo() ;

// ***********************************************************
string   typetoString( string  temp) ;
void settype( JPType  thetype) ;
void setvalue( string  thevalue);

JPType gettype() ;
string  getvalue();

private :

   JPType  type;
   string        value ; 

};





/////////////////////////////////////////////////
class  ClassPC {
public: 
  



   ClassPC();
   ClassPC( JPType thetype, string thevalue) ;
void   printinfo() ;

// ***********************************************************
string   typetoString( string  temp) ;
// ***********************************************************
                  ;
  
void settype( JPType  thetype) ;
void setvalue( string  thevalue);

JPType gettype(); 
string  getvalue();


private:

   JPType  type;
   string   value; };



      ClassPC::ClassPC() { type=NAMEMATCH; value="";}
   ClassPC::ClassPC( JPType thetype, string thevalue) 

	{ type=thetype;
	  value=thevalue;
 	}
void   ClassPC::printinfo() 

                {   string temp;

                    cout << " class  pointcut type is "<<typetoString(temp)<<"\n";
                    cout << " class pointcut value is "<<getvalue()<<"\n";
                }   ;

// ***********************************************************
  
void ClassPC::settype( JPType  thetype) {type=thetype; } 
void ClassPC::setvalue( string  thevalue) {value=thevalue; } 

JPType ClassPC::gettype() { return type;}
string  ClassPC::getvalue() { return value;}

/////////////////////////////////////////////////
class  InstancePC {
public: 
 
   InstancePC();
   InstancePC( JPType thetype, string thevalue) ;

	
void   printinfo() ;

             

// ***********************************************************
string   typetoString( string  temp) ;
  
void settype( JPType  thetype); 
void setvalue( string  thevalue); 

JPType gettype(); 
string  getvalue();


private :

   JPType  type;
   string        value ; };





/////////////////////////////////////////////////
class  MethodPC {
public: 

   MethodPC(); 
   MethodPC( JPType thetype, string thevalue) ;
   void   printinfo() ;
// ***********************************************************
string   typetoString( string  temp) ;
// ***********************************************************
  
void settype( JPType  thetype) ;
void setvalue( string  thevalue);

JPType gettype();
string  getvalue();

private :

   JPType  type;
   string        value ; };



/////////////////////////////////////////////////
class  NetworkPC {
public: 
 


     NetworkPC(); 
   NetworkPC( NetworkType thetype, string thevalue) ;
void   printinfo() ;

// ***********************************************************
string   typetoString( string  temp) ;
  
void settype( NetworkType  thetype) ;
void setvalue( string  thevalue) ;

NetworkType gettype();
string  getvalue() ;

private :

   NetworkType  type;
   string        value ; };



MethodPC::MethodPC() { type=NAMEMATCH; value="";}
   MethodPC::MethodPC( JPType thetype, string thevalue) 

	{ type=thetype;
	  value=thevalue;
 	}
void   MethodPC::printinfo() 

                {   string temp;

                    cout << " method  pointcut type is "<<typetoString(temp)<<"\n";
                    cout << " method  pointcut value is "<<getvalue()<<"\n";
                }   ;



  
void MethodPC::settype( JPType  thetype) {type=thetype; } 
void MethodPC::setvalue( string  thevalue) {value=thevalue; } 

JPType MethodPC::gettype() { return type;}
string  MethodPC::getvalue() { return value;}


/////////////////////////////////////////////////
class  ThreadPC {
public: 
   

      ThreadPC() ;
   ThreadPC( JPType thetype, string thevalue) ;
void   printinfo() ;

// ***********************************************************
string   typetoString( string  temp) ;
void settype( JPType  thetype) ;
void setvalue( string  thevalue);

JPType gettype() ;
string  getvalue();

private :

   JPType  type;
   string        value; };


/////////////////////////////////////////////////
class  VariablePC {
public: 
    VariablePC() ; 
   VariablePC( JPType thetype, string thevalue) ;


void   printinfo() ;

// ***********************************************************
string   typetoString( string  temp) ;
  
void settype( JPType  thetype) ;
void setvalue( string  thevalue);

JPType gettype() ;
string  getvalue() ;

private :

   JPType  type;
   string         value ; };


/////////////////////////////////////////////////
class  PCD {
public: 
  PCD() ;
 PCD(NetworkPC thenetworkPC, ApplicationPC theapplicationPC,ThreadPC thethreadPC,ClassPC theclassPC,InstancePC theinstancePC,MethodPC themethodPC,VariablePC thevariablePC);


 void setnetworkPC( NetworkPC  thenetworkPC) ;
 void setapplicationPC( ApplicationPC  theapplicationPC) ;
 void setthreadPC( ThreadPC  thethreadPC) ;
 void setclassPC( ClassPC  theclassPC) ;
 void setinstancePC( InstancePC  theinstancePC) ;
 void setmethodPC( MethodPC  themethodPC) ;
 void setvariablePC( VariablePC  thevariablePC) ;
 void settext( string  thetext) ;
 void printinfo() ;



 NetworkPC  getnetworkPC();
 ApplicationPC  getapplicationPC();
 ThreadPC  getthreadPC() ;
 ClassPC  getclassPC() ;
 InstancePC  getinstancePC();
 MethodPC  getmethodPC() ;
 VariablePC  getvariablePC() ;
 string  gettext() ;


private :

   NetworkPC     networkPC;
   ApplicationPC applicationPC;
   ThreadPC      threadPC;
   ClassPC       classPC;
   InstancePC    instancePC;
   MethodPC      methodPC;
   VariablePC    variablePC;    
   string          text ; };


   
   
    PCD::PCD() {};
 PCD::PCD(NetworkPC thenetworkPC, ApplicationPC theapplicationPC,ThreadPC thethreadPC,ClassPC theclassPC,InstancePC theinstancePC,MethodPC themethodPC,VariablePC thevariablePC)


	{networkPC=thenetworkPC;
	applicationPC=theapplicationPC;
	threadPC=thethreadPC;
	classPC=theclassPC;
	instancePC=theinstancePC;
	methodPC=themethodPC;
	variablePC=thevariablePC;
	}



 void PCD::setnetworkPC( NetworkPC  thenetworkPC) {networkPC=thenetworkPC; } 
 void PCD::setapplicationPC( ApplicationPC  theapplicationPC) {applicationPC=theapplicationPC; } 
 void PCD::setthreadPC( ThreadPC  thethreadPC) {threadPC=thethreadPC; } 
 void PCD::setclassPC( ClassPC  theclassPC) {classPC=theclassPC; } 
 void PCD::setinstancePC( InstancePC  theinstancePC) {instancePC=theinstancePC; } 
 void PCD::setmethodPC( MethodPC  themethodPC) {methodPC=themethodPC; } 
 void PCD::setvariablePC( VariablePC  thevariablePC) {variablePC=thevariablePC; } 
 void PCD::settext( string  thetext) {text=thetext; } 
 void PCD::printinfo() {};



 NetworkPC  PCD::getnetworkPC() { return   networkPC;}
 ApplicationPC  PCD::getapplicationPC() { return  applicationPC;}
 ThreadPC  PCD::getthreadPC() { return threadPC;}
 ClassPC  PCD::getclassPC() { return classPC;}
 InstancePC  PCD::getinstancePC() { return instancePC;}
 MethodPC  PCD::getmethodPC() { return methodPC;}
 VariablePC  PCD::getvariablePC() { return variablePC;}
 string  PCD::gettext() { return text ;}
/////////////////////////////////////////////////
class WeaveSpecs 
{
public:
 WeaveSpecs () ;
 WeaveSpecs ( WeaveTarget theweavetarget,WeaveType theweavetype ) ;
  void setweavetarget( WeaveTarget  theweavetarget);
  void setweavetype( WeaveType  theweavetype) ;
  WeaveTarget  getweavetarget();
  WeaveType  getweavetype() ;

private:
  WeaveTarget   weavetarget;
  WeaveType     weavetype;
  
};

  WeaveSpecs::WeaveSpecs () {};
  WeaveSpecs::WeaveSpecs ( WeaveTarget theweavetarget,WeaveType theweavetype ) {
	weavetarget=theweavetarget;
	weavetype=theweavetype;};
  
  void WeaveSpecs::setweavetarget( WeaveTarget  theweavetarget) {weavetarget=theweavetarget; } 
  void WeaveSpecs::setweavetype( WeaveType  theweavetype) {weavetype=theweavetype; } 
  WeaveTarget  WeaveSpecs::getweavetarget() { return weavetarget;}
  WeaveType  WeaveSpecs::getweavetype() { return weavetype;}
  
/////////////////////////////////////////////////  
  




class Aspect{

public:
 
 PCD         getpcd () ;

   Aspect() ;
  Aspect(WeaveSpecs  theweavespecs, PCD  thepcd);
 void   setweavespecs( WeaveSpecs theweavespecs);
 void   setpcd( PCD thepcd) ;
 string GetJPMethodName();
 string GetJPClassName();
 WeaveSpecs   getweavespecs();
 string  aspect_type;
 string  aspect_instance;
 short id;
 int method_id;


protected:

  WeaveSpecs   weavespecs;
  PCD          pcd;
 
};

 Aspect::Aspect() {};
 Aspect::Aspect(WeaveSpecs  theweavespecs, PCD  thepcd)
     { weavespecs= theweavespecs;
       pcd = thepcd; };

 void  Aspect::setweavespecs( WeaveSpecs theweavespecs) {weavespecs= theweavespecs;};
 void  Aspect::setpcd( PCD thepcd) {pcd = thepcd;};
 WeaveSpecs  Aspect::getweavespecs() {return weavespecs;};
 PCD         Aspect::getpcd () {return pcd;};

struct Message {
	 char ver;
	 char comm;
	 short len;
	 string data; };



short ToPCD( Message msg, PCD & pcd);
//*****************************************************************************
string ToStr( Message msg);
//*****************************************************************************

Message ToMsg( string str);
//**********************************************
// to be used by messages 1,2 and 10
Message ToMsg( int type, string str);

/*
message   message           purpose 
type      code      
========================================
M1         '1'            client register with CHA
M2         'a'            CHA respond back with applicaiton mangled name  
M3         '2'            client request to see if any weaving/unweaving request 
M4         'b'            CHA respond back Y or N. if Y, then message M5 and M6 
M5         '3'            client request weaving/unweaving packet from CHA
M6         'c'            CHA respnd back with the packet
M7         'd'            CHA receives a weave/unweave request form SHA   
M8         '4'            server send a weave  request to SHA
M9         '5'            server send a unweave request to SHA
M10        '6'            client unregister with CHA
M11        'e'            CHA respond back with ack.
*/


//**********************************************
// to be used by messages 8 and 9
// message contain a pcd
	   // pcd format   in msg.data  aspect_instance_name:nettype+netinfo:apptype+appinfo:threadtype+threadinfo: continue next line
	   // classtype,classinfo:instancetype,instanceinfo:methodtype,methodinfo:varaiabletype,variableinfo:
	   // msg.len indicates the length of the data part 

Message ToMsg( int type, PCD pcd,WeaveSpecs ws, string inst_name, short asp_id);
WeaveSpecs ToWeaveSpecs(Message msg);
void RegisterApplication(string appname);

void RegisterRole( RoleType r);
UINT aopengine_thread( LPVOID pParam );
//****************************************************************************

void startup();
void check_for_requests();

 class namenode 
{
public:
	namenode () ;
 namenode ( string thetext, namenode * thenext);

  namenode * getnext() const ;
  void   settext( string thedata) ;
  string    gettext() ;

  void   setnext( namenode * pointer)  ;

private:
  string text;
  namenode * next;
};

typedef namenode * namenodeptr;



//*****************************************************************
//*****************************************************************

  void  addhead_name( namenodeptr & head, namenodeptr & tail,namenodeptr data);

//*****************************************************************
//*****************************************************************

  void freelist_name ( namenodeptr &head);

//*****************************************************************
//*****************************************************************

    
  void  printlist_name ( namenodeptr  head);
//*****************************************************************
//*****************************************************************
  void  addtail_name( namenodeptr & head, namenodeptr & tail,namenodeptr data );
//*****************************************************************
//*****************************************************************

    
  int  searchlist_name ( namenodeptr  head, string key);

void DAC_INIT();

void DAC_SYNC();


 VariablePC::VariablePC() { type=NAMEMATCH; value="";}
   VariablePC::VariablePC( JPType thetype, string thevalue) 

	{ type=thetype;
	  value=thevalue;
 	}
void   VariablePC::printinfo() 

                {   string temp;

                    cout << " variable pointcut type is "<<typetoString(temp)<<"\n";
                    cout << " variable pointcut value is "<<getvalue()<<"\n";
                }   

// ***********************************************************
string   VariablePC::typetoString( string  temp) 
        {    
      
             switch (type) {
             case  ALL : 
                   temp="ALL";
                   break;   
             case  GROUPJP : 
                   temp="GROUP";
		   break;
             case  NAMEMATCH : 
                   temp="NAMEMATCH";
                   break;
            
             default :
                    temp="error";
              } // end of switch 
             return temp;  
     }

// ***********************************************************
                  ;
  
void VariablePC::settype( JPType  thetype) {type=thetype; } 
void VariablePC::setvalue( string  thevalue) {value=thevalue; } 

JPType VariablePC::gettype() { return type;}
string  VariablePC::getvalue() { return value;}







 ThreadPC::ThreadPC() { type=NAMEMATCH;value="";}
   ThreadPC::ThreadPC( JPType thetype, string thevalue) 

	{ type=thetype;
	  value=thevalue;
 	}
void   ThreadPC::printinfo() 

                {   string temp;

                    cout << " thread pointcut type is "<<typetoString(temp)<<"\n";
                    cout << " thread pointcut value is "<<getvalue()<<"\n";
                }   

// ***********************************************************
string   ThreadPC::typetoString( string  temp) 
        {    
      
             switch (type) {
             case  ALL : 
                   temp="ALL";
                   break;   
             case  GROUPJP : 
                   temp="GROUP";
		   break;
             case  NAMEMATCH : 
                   temp="NAMEMATCH";
                   break;
            
             default :
                    temp="error";
              } // end of switch 
             return temp;  
     }

// ***********************************************************
                  ;
  
void ThreadPC::settype( JPType  thetype) {type=thetype; } 
void ThreadPC::setvalue( string  thevalue) {value=thevalue; } 

JPType ThreadPC::gettype() { return type;}
string  ThreadPC::getvalue() { return value;}







  InstancePC::InstancePC() { type=NAMEMATCH;value="";}
   InstancePC::InstancePC( JPType thetype, string thevalue) 

	{ type=thetype;
	  value=thevalue;
 	}
void   InstancePC::printinfo() 

                {   string temp ;

                    cout << " instance pointcut type is "<<typetoString(temp)<<"\n";
                    cout << " instance pointcut point value is "<<getvalue()<<"\n";
                }   

// ***********************************************************
string   InstancePC::typetoString( string  temp) 
        {    
      
             switch (type) {
             case  ALL : 
                   temp="ALL";
                   break;   
             case  GROUPJP : 
                   temp="GROUP";
		   break;
             case  NAMEMATCH : 
                   temp="NAMEMATCH";
                   break;
            
             default :
                    temp="error";
              } // end of switch 
             return temp;  
     }

// ***********************************************************
                  ;
  
void InstancePC::settype( JPType  thetype) {type=thetype; } 
void InstancePC::setvalue( string  thevalue) {value=thevalue; } 

JPType InstancePC::gettype() { return type;}
string  InstancePC::getvalue() { return value;}


ApplicationPC::ApplicationPC() { type=NAMEMATCH; value="";}
   ApplicationPC::ApplicationPC( JPType thetype, string thevalue) 

	{ type=thetype;
	  value=thevalue;
 	}
void   ApplicationPC::printinfo() 

                {   string temp;

                    cout << " application  pointcut type is "<<typetoString(temp)<<"\n";
                    cout << " application  pointcut value is "<<getvalue()<<"\n";
                }   

// ***********************************************************
string   ApplicationPC::typetoString( string  temp) 
        {    
      
             switch (type) {
             case  ALL : 
                   temp="ALL";
                   break;   
             case  GROUPJP : 
                   temp="GROUP";
		   break;
             case  NAMEMATCH : 
                   temp="NAMEMATCH";
                   break;
            
             default :
                    temp="error";
              } // end of switch 
             return temp;  
     }

// ***********************************************************
                  ;
  
void ApplicationPC::settype( JPType  thetype) {type=thetype; } 
void ApplicationPC::setvalue( string  thevalue) {value=thevalue; } 

JPType ApplicationPC::gettype() { return type;}
string  ApplicationPC::getvalue() { return value;}



NetworkPC::NetworkPC() { type=LOCAL;}
   NetworkPC::NetworkPC( NetworkType thetype, string thevalue) 

	{ type=thetype;
	  value=thevalue;
 	}
void   NetworkPC::printinfo() 

                {   string temp;

                    cout << " network joint point type is "<<typetoString(temp)<<"\n";
                    cout << " network joint point value is "<<getvalue()<<"\n";
                }   

// ***********************************************************
string   NetworkPC::typetoString( string  temp) 
        {    
      
             switch (type) {
             case  BROADCAST : 
                   temp="BROADCAST";
                   break;   
             case  SUBNET : 
                   temp="SUBNET";
		   break;
             case  MULTICAST : 
                   temp="MULTICAST";
                   break;

             case  HOST : 
                   temp="HOST";
                   break; 
             case  LOCAL : 
                   temp="LOCAL";
                   break;
             default :
                    temp="error";
              } // end of switch 
             return temp;  
     }

// ***********************************************************
                  ;
  
void NetworkPC::settype( NetworkType  thetype) {type=thetype; } 
void NetworkPC::setvalue( string  thevalue) {value=thevalue; } 

NetworkType NetworkPC::gettype() { return type;}
string  NetworkPC::getvalue() { return value;}


string   ClassPC::typetoString( string  temp) 
        {    
      
             switch (type) {
             case  ALL : 
                   temp="ALL";
                   break;   
             case  GROUPJP : 
                   temp="GROUP";
		   break;
             case  NAMEMATCH : 
                   temp="NAMEMATCH";
                   break;
            
             default :
                    temp="error";
              } // end of switch 
             return temp;  
     }

	 
string   MethodPC::typetoString( string  temp) 
        {    
      
             switch (type) {
             case  ALL : 
                   temp="ALL";
                   break;   
             case  GROUPJP : 
                   temp="GROUP";
		   break;
             case  NAMEMATCH : 
                   temp="NAMEMATCH";
                   break;
            
             default :
                    temp="error";
              } // end of switch 
             return temp;  
     }	 

	  
	 
	 

 namenode::namenode () {};
 namenode::namenode ( string thetext, namenode * thenext){
            
              text=thetext;
              next=thenext;
              }

   namenode * namenode::getnext() const { return next;}

  void   namenode::settext( string  thedata) { text=thedata;}
  string    namenode::gettext()  {return text;}

  void   namenode::setnext( namenode * pointer) { next=pointer;}


//*****************************************************************
//*****************************************************************

  void  addhead_name( namenodeptr & head, namenodeptr & tail,namenodeptr data)

                { 
                  data->setnext(head);  
                  head=data;
                  if (tail==NULL) 
                        tail=head;  }
//*****************************************************************
//*****************************************************************

  void freelist_name ( namenodeptr &head) 
       {
           namenodeptr tmp;
          
           while (head!=NULL)
                { tmp=head->getnext();
                  delete head;
                  head= tmp;
                }    
          } // end of free list
//*****************************************************************
//*****************************************************************

    
  void  printlist_name ( namenodeptr  head)
   { 
      int i=0;
      while (head !=NULL)
         { 
           cout << " text is " <<head->gettext()<<"\n";
           i++;
           head=head->getnext(); 
         } // end of while
    
   } // end of printlist function
//*****************************************************************
//*****************************************************************
  void  addtail_name( namenodeptr & head, namenodeptr & tail,namenodeptr data )
                { 
                  data->setnext(NULL);
                    if (head ==NULL) 
                      head=tail=data;
                    else
                  {  
                    tail->setnext(data);
                    tail=data;
                  } 
           }



//*****************************************************************
//*****************************************************************

    
  int  searchlist_name ( namenodeptr  head, string key)
   { 
      int i=0,loc=-1;
      int found=0;
      while ((head !=NULL) &&( !found))
         if ( head->gettext().compare(key)==0) 
           { found=1; loc =i; }
         else          
           { i++; head=head->getnext(); }  
   
   return loc;
      
   } // end of searchlist function

   
   
 


	 
	 #endif
